use anyhow::Result;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemProxyConfig {
    pub enable: bool,
    pub server: String,
    pub port: u16,
    pub bypass: Vec<String>,
}

impl Default for SystemProxyConfig {
    fn default() -> Self {
        Self {
            enable: false,
            server: "127.0.0.1".to_string(),
            port: 8888,
            bypass: vec![
                "localhost".to_string(),
                "127.*".to_string(),
                "10.*".to_string(),
                "172.16.*".to_string(),
                "172.17.*".to_string(),
                "172.18.*".to_string(),
                "172.19.*".to_string(),
                "172.20.*".to_string(),
                "172.21.*".to_string(),
                "172.22.*".to_string(),
                "172.23.*".to_string(),
                "172.24.*".to_string(),
                "172.25.*".to_string(),
                "172.26.*".to_string(),
                "172.27.*".to_string(),
                "172.28.*".to_string(),
                "172.29.*".to_string(),
                "172.30.*".to_string(),
                "172.31.*".to_string(),
                "192.168.*".to_string(),
                "<local>".to_string(),
            ],
        }
    }
}

// Windows 系统代理设置
#[cfg(windows)]
pub mod windows {
    use super::*;
    use winreg::enums::*;
    use winreg::RegKey;
    use ::windows::Win32::Networking::WinInet::{InternetSetOptionW, INTERNET_OPTION_SETTINGS_CHANGED};
    use std::ptr;

    pub fn set_system_proxy(config: &SystemProxyConfig) -> Result<()> {
        let hkcu = RegKey::predef(HKEY_CURRENT_USER);
        let internet_settings = hkcu.open_subkey_with_flags(
            "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
            KEY_SET_VALUE,
        )?;

        if config.enable {
            // 启用代理
            internet_settings.set_value("ProxyEnable", &1u32)?;
            
            // 设置代理服务器
            let proxy_server = format!("{}:{}", config.server, config.port);
            internet_settings.set_value("ProxyServer", &proxy_server)?;
            
            // 设置代理例外
            let bypass_list = config.bypass.join(";");
            internet_settings.set_value("ProxyOverride", &bypass_list)?;
        } else {
            // 禁用代理
            internet_settings.set_value("ProxyEnable", &0u32)?;
        }

        // 刷新系统设置
        unsafe {
            let _ = InternetSetOptionW(
                None,
                INTERNET_OPTION_SETTINGS_CHANGED,
                Some(ptr::null_mut()),
                0,
            );
        }

        Ok(())
    }

    pub fn get_system_proxy() -> Result<SystemProxyConfig> {
        let hkcu = RegKey::predef(HKEY_CURRENT_USER);
        let internet_settings = hkcu.open_subkey(
            "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
        )?;

        let enable: u32 = internet_settings.get_value("ProxyEnable").unwrap_or(0);
        let proxy_server: String = internet_settings.get_value("ProxyServer").unwrap_or_default();
        let proxy_override: String = internet_settings.get_value("ProxyOverride").unwrap_or_default();

        let (server, port) = if proxy_server.contains(':') {
            let parts: Vec<&str> = proxy_server.split(':').collect();
            (parts[0].to_string(), parts.get(1).unwrap_or(&"8080").parse().unwrap_or(8080))
        } else {
            (proxy_server, 8080)
        };

        let bypass = if proxy_override.is_empty() {
            Vec::new()
        } else {
            proxy_override.split(';').map(|s| s.to_string()).collect()
        };

        Ok(SystemProxyConfig {
            enable: enable == 1,
            server,
            port,
            bypass,
        })
    }
}

// Linux 系统代理设置
#[cfg(target_os = "linux")]
pub mod linux {
    use super::*;
    use std::process::Command;

    pub fn set_system_proxy(config: &SystemProxyConfig) -> Result<()> {
        if config.enable {
            let proxy_url = format!("http://{}:{}", config.server, config.port);
            
            // 设置 GNOME 代理设置
            if let Ok(_) = which::which("gsettings") {
                Command::new("gsettings")
                    .args(&["set", "org.gnome.system.proxy.http", "host", &config.server])
                    .output()?;
                
                Command::new("gsettings")
                    .args(&["set", "org.gnome.system.proxy.http", "port", &config.port.to_string()])
                    .output()?;
                
                Command::new("gsettings")
                    .args(&["set", "org.gnome.system.proxy", "mode", "manual"])
                    .output()?;
            }

            // 设置环境变量（对当前会话有效）
            std::env::set_var("http_proxy", &proxy_url);
            std::env::set_var("https_proxy", &proxy_url);
            std::env::set_var("HTTP_PROXY", &proxy_url);
            std::env::set_var("HTTPS_PROXY", &proxy_url);
            
            if !config.bypass.is_empty() {
                let no_proxy = config.bypass.join(",");
                std::env::set_var("no_proxy", &no_proxy);
                std::env::set_var("NO_PROXY", &no_proxy);
            }
        } else {
            // 禁用代理
            if let Ok(_) = which::which("gsettings") {
                Command::new("gsettings")
                    .args(&["set", "org.gnome.system.proxy", "mode", "none"])
                    .output()?;
            }

            // 清除环境变量
            std::env::remove_var("http_proxy");
            std::env::remove_var("https_proxy");
            std::env::remove_var("HTTP_PROXY");
            std::env::remove_var("HTTPS_PROXY");
            std::env::remove_var("no_proxy");
            std::env::remove_var("NO_PROXY");
        }

        Ok(())
    }

    pub fn get_system_proxy() -> Result<SystemProxyConfig> {
        let mut config = SystemProxyConfig::default();

        // 检查环境变量
        if let Ok(proxy) = std::env::var("http_proxy") {
            if let Ok(url) = url::Url::parse(&proxy) {
                config.enable = true;
                config.server = url.host_str().unwrap_or("127.0.0.1").to_string();
                config.port = url.port().unwrap_or(8080);
            }
        }

        // 检查 GNOME 设置
        if let Ok(_) = which::which("gsettings") {
            if let Ok(output) = Command::new("gsettings")
                .args(&["get", "org.gnome.system.proxy", "mode"])
                .output()
            {
                let mode = String::from_utf8_lossy(&output.stdout).trim().replace("'", "");
                if mode == "manual" {
                    config.enable = true;
                    
                    if let Ok(output) = Command::new("gsettings")
                        .args(&["get", "org.gnome.system.proxy.http", "host"])
                        .output()
                    {
                        config.server = String::from_utf8_lossy(&output.stdout).trim().replace("'", "");
                    }
                    
                    if let Ok(output) = Command::new("gsettings")
                        .args(&["get", "org.gnome.system.proxy.http", "port"])
                        .output()
                    {
                        if let Ok(port) = String::from_utf8_lossy(&output.stdout).trim().parse() {
                            config.port = port;
                        }
                    }
                }
            }
        }

        Ok(config)
    }
}

// macOS 系统代理设置
#[cfg(target_os = "macos")]
pub mod macos {
    use super::*;
    use std::process::Command;

    pub fn set_system_proxy(config: &SystemProxyConfig) -> Result<()> {
        // 获取当前网络服务
        let output = Command::new("networksetup")
            .args(&["-listallnetworkservices"])
            .output()?;
        
        let services = String::from_utf8_lossy(&output.stdout);
        let network_services: Vec<&str> = services
            .lines()
            .skip(1) // 跳过第一行标题
            .filter(|line| !line.starts_with("*")) // 跳过禁用的服务
            .collect();

        for service in network_services {
            if config.enable {
                // 启用 HTTP 代理
                Command::new("networksetup")
                    .args(&["-setwebproxy", service, &config.server, &config.port.to_string()])
                    .output()?;
                
                // 启用 HTTPS 代理
                Command::new("networksetup")
                    .args(&["-setsecurewebproxy", service, &config.server, &config.port.to_string()])
                    .output()?;
                
                // 设置代理例外
                if !config.bypass.is_empty() {
                    let bypass_list = config.bypass.join(" ");
                    Command::new("networksetup")
                        .args(&["-setproxybypassdomains", service, &bypass_list])
                        .output()?;
                }
            } else {
                // 禁用代理
                Command::new("networksetup")
                    .args(&["-setwebproxystate", service, "off"])
                    .output()?;
                
                Command::new("networksetup")
                    .args(&["-setsecurewebproxystate", service, "off"])
                    .output()?;
            }
        }

        Ok(())
    }

    pub fn get_system_proxy() -> Result<SystemProxyConfig> {
        let mut config = SystemProxyConfig::default();

        // 获取第一个活动的网络服务的代理设置
        let output = Command::new("networksetup")
            .args(&["-listallnetworkservices"])
            .output()?;
        
        let services = String::from_utf8_lossy(&output.stdout);
        if let Some(service) = services.lines().nth(1) {
            if let Ok(output) = Command::new("networksetup")
                .args(&["-getwebproxy", service])
                .output()
            {
                let proxy_info = String::from_utf8_lossy(&output.stdout);
                for line in proxy_info.lines() {
                    if line.starts_with("Enabled: Yes") {
                        config.enable = true;
                    } else if line.starts_with("Server: ") {
                        config.server = line.replace("Server: ", "");
                    } else if line.starts_with("Port: ") {
                        if let Ok(port) = line.replace("Port: ", "").parse() {
                            config.port = port;
                        }
                    }
                }
            }
        }

        Ok(config)
    }
}

// 跨平台接口
pub fn set_system_proxy(config: &SystemProxyConfig) -> Result<()> {
    #[cfg(windows)]
    return windows::set_system_proxy(config);
    
    #[cfg(target_os = "linux")]
    return linux::set_system_proxy(config);
    
    #[cfg(target_os = "macos")]
    return macos::set_system_proxy(config);
    
    #[cfg(not(any(windows, target_os = "linux", target_os = "macos")))]
    Err(anyhow::anyhow!("不支持的操作系统"))
}

pub fn get_system_proxy() -> Result<SystemProxyConfig> {
    #[cfg(windows)]
    return windows::get_system_proxy();
    
    #[cfg(target_os = "linux")]
    return linux::get_system_proxy();
    
    #[cfg(target_os = "macos")]
    return macos::get_system_proxy();
    
    #[cfg(not(any(windows, target_os = "linux", target_os = "macos")))]
    Ok(SystemProxyConfig::default())
}
